import find from './find'
import follow from './follow'

export interface INode {
    className: string;
    id: string | null;
    text: string;
    selected: boolean;
    clickable: boolean;
    childCount: number;
    desc: string | null;
    children: INode[];
}
export enum PatchType {
    ChangeProps = 'ChangeProps',
    ChangeInnerText = 'ChangeInnerText',
    Replace = 'Replace'
}
export function diff(oldTree: INode, newTree: INode) {
    const patches: any[] = []
    const globalIndex = 0;
    dfsWalk(oldTree, newTree, globalIndex, patches);
    return patches;
}
function diffChildren(oldChildren: INode[], newChildren: INode[], index: number, patches: any[]) {
    for (let i = 0; i < oldChildren.length; i++) {
        index = dfsWalk(oldChildren[i], newChildren[i], index, patches);
    }
    return index;
}
export function dfsWalk(oldNode: INode, newNode: INode, index: number, patches: any[] = []) {
    let curPatch = [];
    let nextIndex = index + 1;
    if (!newNode) {
        //如果没有传入新节点则什么都不做
    } else if (newNode.className === oldNode.className && newNode.id === oldNode.id) {
        //节点相同，开始判断属性(未写key时都是undefined，也是相等的)
        const { children: oldChildren, childCount: oldChildCount, ...oldProps } = oldNode;
        const { children: newChildren, childCount: newChildCount, ...newProps } = newNode;
        let props = diffProps(oldProps, newProps);
        if (props.length) {
            curPatch.push({ type: PatchType.ChangeProps, props });
        }
        //如果有子树则遍历子树
        if (oldChildren.length > 0) {
            nextIndex = diffChildren(oldNode.children, newNode.children, nextIndex, patches);
        }
    } else {
        //节点tagName或key不同
        curPatch.push({ type: PatchType.Replace, node: newNode });
    }
    //将收集的变化添加至补丁包
    if (curPatch.length > 0) {
        if (patches[index]) {
            patches[index] = patches[index].concat(curPatch);
        } else {
            patches[index] = curPatch;
        }
    }
    //为追踪节点索引，需要将索引返回出去
    return nextIndex;
}
export interface PropPatch {
    type: 'selected';
    from: boolean;
    to: boolean;
}
function diffProps(oldProps: Pick<INode, 'className' | 'id' | 'desc' | 'selected' | 'text'>, newProps: Pick<INode, 'className' | 'id' | 'desc' | 'selected' | 'text'>) {
    let propPatch: PropPatch[] = [];
    const { desc: oldDesc, selected: oldSelected, text: oldText } = oldProps;
    const { desc: newDesc, selected: newSelected, text: newText } = newProps;
    if (oldSelected !== newSelected) {
        const oldTitle = oldDesc || oldText
        const newTitle = newDesc || newText
        if (oldTitle && newTitle && oldTitle === newTitle) {
            propPatch.push({
                type: 'selected',
                from: oldSelected,
                to: newSelected,
            })
            console.log(oldProps.id, oldProps.className)
        }
    }
    return propPatch;
}

const d = diff(find, follow)

console.log(d)